#include "DGL3Common.glsl"
#include "DGL3PickCommon.glsl"
#include "DGL3ProgramEnums.inc"

//-----------------------------------------

#ifdef VERTEX_SHADER

	layout(location = 0) in vec3 aPosition;
	layout(location = GE_VA_Transform) in ivec2 aAssigns;

	void main(void)
	{
		gl_Position = GetModelMatrix(aAssigns.x) * vec4(aPosition, 1.0);
	}

#endif

//-----------------------------------------

#ifdef GEOMETRY_SHADER

	layout(triangles) in;
	layout(points, max_vertices = 5) out;

	uniform vec3 uRayOrigin;
	uniform vec3 uRayDirection;
	uniform vec2 uRayOrigin2d;
	uniform float uTolerance;

	// position in normalized device coordinates
	out vec3 ndcPos;
		
	void main(void)
	{
		float t, u, v;
		bool isParallel = !RayTriangleIntersection3d(uRayOrigin, uRayDirection, gl_in[0].gl_Position.xyz, gl_in[1].gl_Position.xyz, gl_in[2].gl_Position.xyz, t, u, v);
		if (isParallel)
			return;

		if (t >= 0 && u >= 0 && v >= 0 && u+v <= 1)
		{
			gl_Position = uProjectionMatrix * uViewMatrix * vec4(uRayDirection * t + uRayOrigin, 1.0);
			ndcPos = gl_Position.xyz / gl_Position.w;

			gl_Position.w = 1000.0;

			EmitVertex();
			EndPrimitive();
		}
		else if (uTolerance > EPS)
		{
			int index1;
			int index2;
			if (v < 0)
			{
				index1 = 0;
				index2 = 1;
			}
			else if (u < 0)
			{
				index1 = 0;
				index2 = 2;
			}
			else if (u + v > 1)
			{
				index1 = 1;
				index2 = 2;
			}

			vec4 screenPos4 = uProjectionMatrix * uViewMatrix * gl_in[index1].gl_Position;
			vec2 screenPosition1 = screenPos4.xy / screenPos4.w;
			
			screenPos4 = uProjectionMatrix * uViewMatrix * gl_in[index2].gl_Position;
			vec2 screenPosition2 = screenPos4.xy / screenPos4.w;
			
			if (LineSegmentIntersect2d(uRayOrigin2d, screenPosition1, screenPosition2, uTolerance))
			{
				vec3 hitPoint;
				if (FindHitPointToLine3d(uRayOrigin, uRayDirection, gl_in[index1].gl_Position.xyz, gl_in[index2].gl_Position.xyz, hitPoint))
				{
					gl_Position = uProjectionMatrix * uViewMatrix * vec4(hitPoint, 1.0);
					ndcPos = gl_Position.xyz / gl_Position.w;
				
					EmitVertex();
					EndPrimitive();
				}
			}
		}
	}

#endif

#ifdef FRAGMENT_SHADER

	in vec3 ndcPos;
	
	layout(location = 0) out vec4 fragColor;
	
	void main(void)
	{
		// convert ndcPos from range [-1;1] to range [0;1]
		fragColor = vec4((ndcPos.xyz + 1.0) / 2.0, 0.0);
	}

#endif

//-----------------------------------------

#ifdef RECT_TEST_VERTEX_SHADER

	layout(location = 0) in vec3 aPosition;
	layout(location = GE_VA_Transform) in ivec2 aAssigns;
	
	out vec2 pos2d;

	void main(void)
	{
		vec4 screenPos4 = (uProjectionMatrix * uViewMatrix * GetModelMatrix(aAssigns.x)) * vec4(aPosition, 1.0);
		pos2d = screenPos4.xy / screenPos4.w;
	}

#endif

#ifdef RECT_TEST_FRAGMENT_SHADER

	layout(location = 0) out vec4 fragColor;

	void main(void)
	{		
		fragColor = vec4( COLOR_INCREMENT, 0.0, 0.0, 1.0 );
	}

#endif

#ifdef RECT_TEST_GEOMETRY_SHADER

	layout(triangles) in;
	layout(points, max_vertices = 2) out;

	uniform vec2 uLeftBottom;
	uniform vec2 uRightTop;

	in vec2 pos2d[];
	
	void main(void)
	{
		gl_Position = TOTAL_POSITION;
		
		EmitVertex();
		EndPrimitive();	
		
		int count = 0;
		
		if (IsPointInsideRect( pos2d[0], uLeftBottom, uRightTop))
			count++;
		if (IsPointInsideRect(pos2d[1], uLeftBottom, uRightTop))
			count++;
		if (IsPointInsideRect(pos2d[2], uLeftBottom, uRightTop))
			count++;

		if (count > 0)
		{
			if (count == 3)
				gl_Position = INSIDE_POSITION;
			else if (count == 2 || count == 1)
				gl_Position = INTERSECT_POSITION;
				
			EmitVertex();
			EndPrimitive();		
		}
		else
		{
			if (SegmentRectangleIntersection2d(pos2d[0], pos2d[1], uLeftBottom, uRightTop) ||
				SegmentRectangleIntersection2d(pos2d[1], pos2d[2], uLeftBottom, uRightTop) ||
				SegmentRectangleIntersection2d(pos2d[2], pos2d[0], uLeftBottom, uRightTop))
			{
				gl_Position = INTERSECT_POSITION;
				
				EmitVertex();
				EndPrimitive();	
			}
		}
	}

#endif
